home *** CD-ROM | disk | FTP | other *** search
- COMMENT \
- Filter TOPS-20 sequence numbers from the standard input file. These
- consist of sequences nnnn<Bn><09> at the beginning of each line. That
- is, the fifth character is a digit <3n> which has been OR'ed with <80>.
- This is how Kermit flags the fifth character from a DEC-20 36-bit word
- in which the rightmost bit is 1. Trailing blanks are also trimmed. If
- any single line is longer than the internal line buffer size (256), it
- will be output unprocessed and a warning message will be issued. This
- should be rare, and if the number of occurrences is small, hand editing
- of the output file could fix the problem.
-
- Usage: deseq <inputfile >outputfile
-
- Error return codes:
- 0 - normal termination
- 1 - write error on standard output file (usually because disk full);
- an error message is printed.
-
- {Adapted from a disassembly of the IBM utility MORE.COM and commented
- with a view to being a model for further simple filters.}
-
- For efficiency, input and output characters are handled in large buffers.
-
- [28-Jan-84]
- \
-
- assume cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
- deseqc segment para public 'code'
-
- include dos.inc
- include ascii.inc
-
- org 100h ; this is a .COM file
- DEBUG equ 0 ; non-zero for built-in input file test
-
- ; Sum of buffer sizes can be 64K-(code + otherdata size), or about 40K total
-
- MAXOUTBUF equ 16384 ; Output buffer size
- MAXINBUF equ 16384 ; Input buffer size
- MAXLINBUF equ 256 ; Line buffer size
-
- deseq proc near
- call check_dos_version
- if DEBUG
- mov dx,offset debugfn
- mov al,$DOS_OPEN2_READ
- mov ah,$DOS_OPEN2
- int $DOS
- jnc openok
- int $HALT ; open failure
- openok:
- mov debugin,ax ; save file handle
- endif
- mov inbuf_prev,0 ; set empty input buffer
- mov inbuf_len,0 ; set empty input buffer
- mov linbuf_len,0 ; set empty line buffer
- mov outbuf_len,0 ; set empty output buffer
-
- readln:
- call get_line ; get an input line
- mov cx,linbuf_len ; Get output line length
- jcxz eof ; No more data, all done
- call strip_line ; Yes, go strip any line number
-
- putlin:
- call trim_line
- call write_line ; go write the line
- jmp short readln ; Loop for next line
-
- eof: ; here at end-of-file
- call write_buf ; write any remaining data
- mov ah,$DOS_EXIT ; all done, no more data
- mov al,0 ; return code
- int $DOS ; terminate
-
- if DEBUG
- even ; align on word boundary
- debugin dw ?
- debugfn db "c:\pascal\foo.for",.NUL
- endif
- even ; align on word boundary
- inbuf_prev dw ? ; Buffer pointer
- inbuf_len dw ? ; Buffer size
- inbuf db MAXINBUF dup (?) ; Input buffer
-
- even ; align on word boundary
- linbuf_len dw ? ; Buffer pointer
- linbuf db MAXLINBUF dup (?) ; Output buffer for line storage
-
- even ; align on word boundary
- outbuf_len dw ? ; Buffer length
- outbuf db MAXOUTBUF dup (?) ; Output buffer for final write
- deseq endp
-
- assume cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
- trim_line proc near
-
- ; Routine to trim trailing white space from line. No action is taken if
- ; the line buffer does not end with CR LF, since in that case, the line
- ; is incomplete (long line split across buffer boundary).
- ; No registers are preserved
-
- mov cx,linbuf_len ; line length
- mov si,offset linbuf-3 ; output buffer address-3
- add si,cx ; address of last character before CR LF
-
- mov al,[si+1] ; get what should be CR
- cmp al,.CR ; was it?
- jne notrim ; no, not really end-of-line
-
- mov al,[si+2] ; get what should be LF
- cmp al,.LF ; was it?
- jne notrim ; no, not really end-of-line
-
- std ; set direction flag to decrement si
-
- trim:
- lodsb ; byte from [si] to al, decrement si
- cmp al," " ; blank?
- je zap_space ; yes
- cmp al,.HT ; tab?
- jne notrim ; no, not white space, so exit loop
- zap_space:
- mov byte ptr [si+1],.NUL ; change blank or tab to NUL
- loop trim ; decrement cx and loop until cx = 0
-
- notrim:
- ret ; return to caller
-
- trim_line endp
-
- assume cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
- strip_line proc near
-
- ; Routine to strip line numbers
- ; No registers are preserved
-
- mov cx,linbuf_len ; line length
- cmp cx,8 ; Possible nnnnn<TAB> .. <CR><LF> on this line?
- jle strip_done ; No, return immediately
- mov si,offset linbuf; line buffer address
- cld ; clear direction flag to increment si
-
- nextch: ; Loop looking for line numbers
- lodsb ; Byte from [si] to al, increment si
- cmp al,128 ; 8-th bit on?
- jb ordchr ; Jump if not
- call check_seq ; Check for sequence number and clear if so
- ordchr: ; Ordinary character
- loop nextch ; Decrement count in cx and loop until cx = 0
-
- strip_done:
- ret ; return to caller
-
- strip_line endp
-
- assume cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
- get_line proc near
-
- ; Routine to get a line from the standard input file, leaving it
- ; in line_buf with its length in line_len. line_len will be zero
- ; on end-of-file.
- ; no registers preserved
-
- getnext:
- call getch ; get next input character
- jz eol ; zero when no more input
- push ax ; save character
- call write ; save in line buffer
- pop ax ; restore character
- cmp al,.LF ; end-of-line yet?
- jne getnext ; jump if not LF
- eol: ; here on eol or possibly eof
- ret ; return to caller
- get_line endp
-
- assume cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
- check_dos_version proc near
-
- ; Routine to check for DOS version 2.00 or later. Aborts with message
- ; if not so.
- ; No registers preserved
-
- mov ah,$DOS_GETVERSION
- int $DOS
- xchg ah,al
- cmp ax,0200h ; DOS 2.00 or later?
- jnb cont ; jump if version >= 2.00
- mov dx,offset baddos
- mov ah,$DOS_STROUT
- int $DOS ; print string to standard output
- int $HALT ; terminate early version of DOS
- cont:
- ret
-
- baddos db "DESEQ: Incorrect DOS version"
- db " -- must run under DOS 2.00 or later"
- db .CR,.LF,"$"
-
- check_dos_version endp
-
- assume cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
- getch proc near
-
- ; Routine to get next character from standard input in al.
- ; Returns with zero flag set on end-of-file, clear otherwise
- ; No registers are preserved
-
- mov bp,inbuf_prev ; Pointer to next available byte in buffer
- cmp bp,inbuf_len ; Bytes left in buffer?
- jl noread ; Yes, no need to read more yet
- mov ah,$DOS_READ2 ; string read code
- if DEBUG
- mov bx,debugin ; file handle
- else
- mov bx,$STDIN ; file handle
- endif
- mov cx,MAXINBUF ; count of bytes to read
- mov dx,offset inbuf ; buffer address
- int $DOS ; read a block of characters
- mov inbuf_len,ax ; number of bytes actually read
- mov inbuf_prev,0 ; Point to last byte returned
- or ax,ax ; test number of bytes obtained
- jz done ; return with zero flag set on EOF
-
- noread:
- mov bp,inbuf_prev ; offset of next character available
- mov al,inbuf[bp] ; get the character from the buffer
- inc inbuf_prev ; increment byte pointer (and set condition
- ; flag to non-zero)
- done:
- ret ; return to caller with zero/non-zero flag set
-
- getch endp
-
- assume cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
- write proc near
-
- ; Routine to write the character in al to the line buffer. If the
- ; buffer is filled, it is automatically written to the standard
- ; output file by a call to write_line and an error message is issued
- ; noting the overflow. Characters are not lost in the output, but
- ; processing on the current line will not be correct.
- ; No registers are preserved
-
- mov bp,linbuf_len ; offset of next available slot in buffer
- cmp bp,MAXLINBUF ; buffer full yet?
- jl nowrite ; no, just add to buffer
- push ax ; yes, save character
- call write_line ; then write the buffer
- push bx ; save registers
- push cx
- push dx
- mov ah,$DOS_WRITE2 ; and write an error message
- mov bx,$STDERR
- mov cx,linemsg_len
- mov dx,offset linemsg
- int $DOS
- pop dx ; restore registers
- pop cx
- pop bx
- pop ax ; and restore the character
- mov bp,0 ; new output buffer length in index register
- mov linbuf_len,bp ; and storage
-
- nowrite: ; here with bp pointing to offset of next char
- mov linbuf[bp],al ; save the character
- inc linbuf_len ; increment output buffer length
- ret ; return to caller
-
- linemsg db "%Long line overflows buffer - processing incomplete",.CR,.LF
- linemsg_len equ $-linemsg
-
- write endp
-
- assume cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
- write_line proc near
-
- ; Routine to write the line buffer to the output buffer. Any NUL's found
- ; are discarded.
- ; No registers are preserved.
-
- mov cx,linbuf_len ; current line length
- jcxz wrdone ; exit if no characters left to write
- mov si,offset linbuf; line buffer address
- mov bx,outbuf_len ; old output buffer length
- lea di,outbuf[bx] ; address of next available char in output
- cld ; clear direction flag to increment si and di
-
- mvbuff: ; copy the buffer discarding NULs
- lodsb ; character from [si] to al, increment si
- cmp al,.NUL ; NUL?
- je mvloop ; yes, skip output
- cmp bx,MAXOUTBUF ; still space in output buffer?
- jl mvchar ; yes, store the character
- call write_buf ; no, empty the buffer
- mov bx,outbuf_len ; old output buffer length
-
- mvchar:
- stosb ; character from al to [di], increment di
- inc bx ; count the character
-
- mvloop:
- loop mvbuff ; decrement cx, and loop while cx > 0
-
- wrdone:
- mov outbuf_len,bx ; update output buffer length
- mov linbuf_len,0 ; indicate empty buffer
- ret ; return to caller
- write_line endp
-
- assume cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
- write_buf proc near
-
- ; Routine to write outbuf buffer to the standard output file.
- ; All registers are preserved.
- ; Error returns from DOS (e.g. disk full) result in an error message
- ; and immediate termination.
-
- push ax ; save registers
- push bx
- push cx
- push dx
- mov ah,$DOS_WRITE2
- mov bx,$STDOUT ; file handle
- mov cx,outbuf_len ; count of bytes to write
- jcxz writeok ; exit if nothing to write
- mov dx,offset outbuf; buffer address
- int $DOS ; write the buffer
- jnc writeok
- mov ah,$DOS_WRITE2 ; write failed, issue message
- mov bx,$STDERR ; file handle
- mov cx,writemsg_len ; count
- mov dx,offset writemsg ; buffer
- int $DOS
- mov ah,$DOS_EXIT
- mov al,1 ; return code
- int $DOS ; abort
-
- writeok:
- mov outbuf_len,0 ; show empty buffer
- pop dx ; restore registers
- pop cx
- pop bx
- pop ax
- ret
-
- writemsg db "?Unrecoverable write error on standard output file",.CR,.LF
- db " Disk probably full",.CR,.LF
- writemsg_len equ $-writemsg
-
- write_buf endp
-
- assume cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
- check_seq proc near
-
- ; Routine to check that we have 5 digits followed by a tab, and if
- ; so, replace it by NULs. On entry, si points to character FOLLOWING
- ; one with bit 8 set, and al contains the latter character.
- ; Preserves all registers
-
- push bx ; save bx
- push ax ; and ax
- cmp byte ptr [si],.HT ; check for following tab
- jne check_done ; jump if not tab
-
- mov bx,-5 ; loop count
-
- check_dig: ; loop testing for digits
- mov al,[si+bx] ; get digit
- cmp bx,-1 ; digit before tab?
- jne no_clear ; jump if not
- and al,7FH ; yes, clear high bit - nnnnN<tab>
-
- no_clear:
- cmp al,.DIGIT0
- jb check_done ; not a digit
- cmp al,.DIGIT9 ;
- ja check_done ; not a digit
- inc bx ; was digit, bx = bx + 1
- jl check_dig ; loop until bx = 0
-
- mov byte ptr [si-5],.NUL ; set the nnnnn<TAB> field to NULs
- mov byte ptr [si-4],.NUL
- mov byte ptr [si-3],.NUL
- mov byte ptr [si-2],.NUL
- mov byte ptr [si-1],.NUL
- mov byte ptr [si],.NUL
-
- check_done:
- pop ax ; restore ax
- pop bx ; restore bx
- ret ; return to caller
- check_seq endp
-
- deseqc ends
- end deseq